package eerbaar.collision.internal;

import eerbaar.collision.ICollisionCallback;
import eerbaar.elements.IElement;
import eerbaar.elements.extension.IEnemyElement;
import eerbaar.elements.extension.IFoodElement;
import eerbaar.elements.extension.ILeaderElement;
import eerbaar.elements.extension.IPackMemberElement;
import eerbaar.elements.extension.IPointConsumer;
import eerbaar.elements.extension.IPointSource;
import eerbaar.elements.extension.IPoints;
import eerbaar.message.lib.CollisionMsg;
import eerbaar.message.lib.DisplayRisingTextMsg;
import eerbaar.message.lib.MsgFactory;
import eerbaar.message.lib.NotifyEatMsg;
import eerbaar.message.lib.NotifyEatPackBoneMsg;
import eerbaar.message.lib.ScoreChangeMsg;
import eerbaar.position.IPosition;
import eerbaar.shared.message.MsgHelper;

class ProximityProcessor extends CollisionProcessor {

    private IElement pet;
    private IElement inputPet;
    private ILeaderElement leader;
    private IElement enemy;
    private IElement pack;

    // private boolean canKillEnemy() {
    //
    // if (this.pack != null && this.enemy != null) {
    //
    // return true;
    // }
    //
    // return false;
    // }

    private boolean canMakePack() {

        if (this.pet != null && this.leader != null) {

            if (this.pack == null) {

                return true;
            }
        }

        return false;
    }

    @Override
    protected boolean canTransferPoints() {

        if (this.pack != null && this.source != null) {

            return true;
        }

        return false;
    }

    public void installPack(ILeaderElement leader, IPackMemberElement pet) {

        leader.add(pet);
    }

    // private void killEnemy(ICollisionCallback callback) {
    //
    // if (this.enemy == null || this.pack == null) {
    //
    // return;
    // }
    //
    // callback.removeElement(this.enemy);
    // }

    private void makePack() {

        if (this.pet == null || this.leader == null) {

            return;
        }

        this.leader.add(this.pet.getExtension(IPackMemberElement.class));

        String description = this.leader.getExtension(IElement.class).getName();
        CollisionMsg msg = MsgFactory.createCollisionMsg(description);
        MsgHelper.sendMsg(CollisionMsg.class, msg);

        new PackWatcher(this.pet.getExtension(IPackMemberElement.class),
                this.leader.getExtension(ILeaderElement.class));
    }

    void processProximity(IElement pet, IElement e1, IElement e2,
            ICollisionCallback callback) {

        if (e1 == e2) {
            return;
        }

        this.inputPet = pet;
        setup(e1, e2);

        // if (canKillEnemy()) {
        //
        // killEnemy(callback);
        // } else if (canMakePack()) {
        if (canMakePack()) {

            makePack();
        } else if (canTransferPoints()) {

            transferPoints(callback);
        }
    }

    @Override
    protected void sendMessages(final int points) {

        MsgHelper.sendMsg(ScoreChangeMsg.class, new ScoreChangeMsg());

        IPosition p = this.source.getPosition();

        MsgHelper.sendMsg(DisplayRisingTextMsg.class, new DisplayRisingTextMsg(
                "+" + points, p.getX(), p.getY()));

        if (this.source.getName().endsWith("bone")) {
            NotifyEatMsg msg = new NotifyEatMsg();
            msg.put("source.name", this.source.getName());
            MsgHelper.sendMsg(NotifyEatMsg.class, msg);
        } else {
            NotifyEatPackBoneMsg msg = new NotifyEatPackBoneMsg();
            msg.put("source.name", this.source.getName());
            MsgHelper.sendMsg(NotifyEatPackBoneMsg.class, msg);
        }
    }

    @Override
    protected void setup(IElement e1, IElement e2) {

        // super.setup(e1, e2);

        IElement[] elements = new IElement[] { e1, e2 };

        for (IElement e : elements) {

            if (e.getName().equals("pet")) {
                this.pet = e;
            }
        }

        for (IElement e : elements) {

            ILeaderElement f = e.getExtension(ILeaderElement.class);

            if (f == null) {
                continue;
            }

            if (this.leader == null) {
                this.leader = f;
            }

            if (f.getMemberCount() > 0) {
                this.pack = e;
            }
        }

        for (IElement e : elements) {

            IPackMemberElement f = e.getExtension(IPackMemberElement.class);

            if (f == null) {
                continue;
            }

            ILeaderElement l = f.getLeader();
            if (l == null) {
                continue;
            }
            if (l.getMemberCount() == 0) {
                continue;
            }

            this.leader = l;
            this.pack = e;
        }

        for (IElement e : elements) {

            IEnemyElement k = e.getExtension(IEnemyElement.class);

            if (k == null) {
                continue;
            }

            if (this.enemy == null) {

                this.enemy = e;
            }
        }

        for (IElement e : elements) {

            IPointSource s = e.getExtension(IPointSource.class);
            if (s == null) {
                continue;
            }

            IPoints points = s.getExtension(IPoints.class);
            if (points.getPoints() == 0) {
                continue;
            }

            if (e != this.inputPet) {

                this.source = e;
            }
        }

    }

    @Override
    protected void transferPoints(ICollisionCallback callback) {

        if (this.leader == null || this.source == null) {

            return;
        }
        if (this.source.getName().startsWith("bone") == false) {

            return;
        }

        IPoints to = this.inputPet.getExtension(IPoints.class);
        IPoints from = this.source.getExtension(IPoints.class);

        if (to != null && from != null) {

            IPointConsumer c = this.inputPet.getExtension(IPointConsumer.class);
            int max = c.getPointsToTake();

            final int points = from.getPoints();
            int take = points;
            if (take > max) {
                take = max;
            }

            to.setPoints(to.getPoints() + take);
            from.setPoints(points - take);

            IFoodElement food = this.source.getExtension(IFoodElement.class);
            if (food != null) {
                callback.removeElement(this.source);
            }

            int display = take;
            sendMessages(display);
        }
    }

}
